ทำไมต้องเป็น Docker
อ้างอิงจากเว็บไซต์ของ Docker เอง ซึ่งกล่าวว่า การพัฒนาแอปพลิเคชันทุกวันนี้ developer ต้องทำอะไรมากกว่าแค่การเขียนโค๊ด เพราะต้องจัดการกับหลายภาษา หลาย framework เครื่องมือที่หลากหลาย และบ่อยครั้งการเชื่อมต่อ (interface) ระหว่างภาษานี้ก็ไม่ได้ทำได้ง่ายๆ เลย นอกจากนั้นแอปพลิเคชันที่สามารถรันได้กับบาง version เท่านั้น ถ้าเอาไปรันกับ version อื่นก็พัง Docker จึงถูกออกแบบให้ง่ายต่อการทำงาน และให้อิสระกับนักพัฒนาในการเลือกเครื่องมือและ environment (OS, tech stack) ในการทำงานแต่ละโปรเจค
The Docker platform
Docker เป็น platform ที่ใช้ในการพัฒนา shipping และรัน application ซึ่งรันอยู่บน environment แยกกันจาก host แบบหลวมๆ ที่เรียกว่า Container และยังสามารถรันหลายๆ Container ใน host เดียวกันได้ด้วย ซึ่ง environment และ security จะแยกขาดจากกันเลย Container นั้นนั้นต่างจาก Hyperviser เพราะรันอยู่บน kernel ของ os และตัดฟังก์ชัน ที่ไม่จำเป็นทิ้ง จึงทำให้ Container นั้นเบากว่า VM มาก
ประโยชน์ของ Docker
ในแง่ของการพัฒนา เราใช้กำหนด standard ของ environment ได้ เมื่อเราต้องการแชร์ให้เพื่อนร่วมงานมาใช้ด้วย เรายังสามารถ push ขึ้นไปเก็บไว้ใน registry ได้ และ registry นี้ ก็เอาไปดีพลอยที่ไหนก็ได้ รวมถึงถ้ามีบัก นักพัฒนาก็เอามาแก้ที่ local และเอาไปดีพลอยได้เลย และเนื่องจาก docker มาขนาดเล็กมาก เราจึงสามารถรันได้มากขึ้น หมายความว่า vm ที่คุณสร้างขึ้นมาเพื่อ run website จากแต่เดิมอาจจะรันได้แค่ 1 เว็บไซต์ เพราะอาจจะเขียนมาจาก java ที่ต้องลง Java Runtime ซึ่งอาจจะมีขนาดใหญ่ จนไม่สามารถลง application อื่นๆ ได้อีก หรืออาจจะเป็นห่วงว่าการลงโปรแกรมอื่นจะทำให้ Application หลักพัง เนื่องจากที่เล่าไปแล้ว ว่า Docker Container มันรันกันแบบขาดจาก Container อื่นๆ จึงสามารถทำให้รันได้แบบไม่ส่งผลต่อกันครับ
Docker Architecture
Docker engine มีลักษณะคล้ายกับ client-server ซึ่ง process ของ docker ที่ทำงานคล้าย server เรียกว่า daemon ส่วนของ Client เราเรียกว่า Docker CLI และแน่นอน คำสั่งต่างๆ ที่สั่งจาก client ก็จะส่งไปหาตัว daemon
Docker daemon ( หรือจะเรียก dockerd ก็ได้ครับ )
จากภาพด้านบน Docker daemon เป็นหัวใจหลักของ docker ครับ มันทำหน้าที่รับคำสั่งจาก client เพื่อไปจัดการกับ objects ไปว่าจะเป็น docker image, container, network, และ volumes ต่างๆ
Docker client
ประกอบด้วยคำสั่งในการติดต่อไปหา dockerd เช่น เมื่อเราสั่งการ docker run ตัว dockerd เองเมื่อรับคำสั่งมาแล้ว ก็จะต้องไปเลือกว่าจะเอา docker image ตัวไหนมารัน ถ้ายังไม่เคยมีบนเครื่อง ก็จะไปหา docker image จาก docker hub มารันให้ซึ่งมี command อื่นๆ อีกหลายตัว เช่น
- docker build
- docker pull
- docker run
Docker registry
registry เอาไว้เก็บ docker image ที่เราสามารถนำไป deploy บน host อื่นๆ หรือส่งให้เพื่อนได้ครับ
Docker objects
เราอาจจะได้ยิน docker image หรือ docker container มาแล้วบ้าง ต่อไปจะไปดูทีละตัวกันครับ ว่ามันคืออะไรกันแน่
Docker Images
ส่วนนี้เป็นพิมพ์เขียวในการสร้าง Docker Container ครับ ตัวอย่างของ image เช่น Ubuntu, Linux, Centos เป็นต้น ซึ่งเราสามารถดู image ที่น่าสนใจได้ที่ docker hub ครับ มีคนสร้างไว้ให้เราได้ใช้มากมาย แต่ต้องดูความน่าเชื่อถือด้วยนะครับ แต่บ่อยครับ เรานี่แหละครับ ที่ต้องเป็นคนสร้าง docker image ใช้เอง โดยการยืม image อื่นๆ มาเป็น base image ซะก่อน และติดตั้งโปรแกรมอื่นๆ ที่เราต้องการเข้าไป รวมโปรแกรมที่เราพัฒนาขึ้นมาด้วย วิธีการสร้างก็ง่ายมากครับ เพียงแค่คุณต้องมี Dockerfile ที่บอกวิธีการสร้าง image แล้วพอสั่ง docker build ตัว dockerd ก็จะจัดการสร้าง image ให้เราครับ บางครั้งเราอาจจะเจอว่า image มีขนาดใหญ่มาก ทั้งๆ ที่ application มีขนาดเล็ก วิธีการแก้ ลองใช้วิธีการ build แบบ multi stage build ดูครับ
Docker Container
container ก็คือ docker images ที่ถูกทำให้รันได้ครับ นอกจากการรัน docker container ขึ้นมาแล้ว ยังสามารถ stop, start container หรือลบ container ไปเลยก็ได้ครับ ซึ่งคำสั่งที่ใช้บ่อยๆ ดังนี้ครับ
- Start Container อ่านเพิ่มเติม
- docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
- Stop Container
- docker stop <container_id
- ลิสต์ container ที่รันอยู่
- docker ps
- ดู log บน container แต่ละตัว
- docker logs <container_id>
- การ remote เข้าไปใน container
- docker exec <container_id> [COMMAND]
- การลบ docker container ที่หยุดแล้ว
- docker rm <container_id>
- การลบ docker container ที่หยุดแล้วทั้งหมด
- docker system prune
Docker Service
โดยปกติแล้ว docker จะแยกตัวเองมาจาก container อื่นๆ แต่บางครั้ง ก็มีคนอยากจะ group รวมกัน ให้จัดการง่ายๆ เช่น เวลาตั้ง application A ต้องมี service A, B, C ... รันด้วย แต่อยากสั่งงานที่เดียว อันนี้จะเป็นประโยชน์ของ docker service ครับ
Container Lifecycle
- ขั้นแรก Docker จะอยู่ Create State ซึ่งเป็นแค่ image ธรรมดาๆ
- เมื่อถูกรันด้วยคำสั่ง docker run ตัว container จะถูกย้ายไปอยู่ running หรือ started state
- สามารถทำให้อยู่ใน paused ได้เมื่อรัน docker pause
- ถ้า container ถูก stop จะไปอยู่ dead state
- ถ้าถูก kill ก็คือไปอยู่ที่ exit state ครับ
Docker Networking อ่านเพิ่มเติม
Networking บน docker มีประเภท ดังนี้ครับ
- bridge => เป็น default networking ครับ อนุญาตให้ container หลายๆ ตัว ที่รันอยู่บน docker daemon เดียวกัน สามารถคุยกันได้ ผ่าน bride IP ครับ ซึ่ง IP นี้ container เท่านั้นครับ ที่คุยกันได้
- host => network ประเภทนี้ จะรันอยู่บน network ของ host จริงๆ เลยครับ สมมติเรารัน container ที่ port 5000 โดยใช้ network แบบ host port ดังกล่าวก็จะถูกใช้งานผ่านทาง host ได้เลยครับ ไม่ต้อง expose port ออกมา
- none => ถ้าใช้เน็ตเวิร์กแบบนี้ ก็คือไม่ให้ container เชื่อมต่อกับใครเลยครับ รันอยู่เงียบๆ คนเดียว
Persist Data
โดยปกติแล้ว นักพัฒนาสามารถ execute เข้าไปใน docker container ได้ครับ สามารถแก้ไขอะไรก็ได้ใน container คล้ายๆ กับ VM เครื่องหนึ่ง แต่เมื่อไรก็ตามที่ container นั้นถูก stop หรือ restart ข้อมูลก็จะหายครับ เช่นเดียวกับ container จำพวก database ถ้าไม่เก็บข้อมูลลงบน disk ถาวร ข้อมูลก็จะหายเช่นกันครับ ในส่วนนี้ ผมจะพูดถึงว่า จะทำยังไง เมื่อ container ถูกลบ แล้วข้อมูลจะไม่หาย ซึ่งก็คือการเก็บข้อมูลไว้ใน persistent disk นั่นเอง สามารถทำได้ดังนี้ครับ
docker run -v <container_path>:<file_system_path> ...
Reference
https://data-flair.training/blogs/docker-container/
https://morioh.com/p/07e61c20c234